//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H

// Test if we have _GNU_SOURCE before the next step will mess up 
// setting __USE_GNU 
// (only needed for gcc-2.95 compatibility, gcc 3.2 always defines it)
#include "wx/setup.h"

// Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org>
// to detect if this is a *BSD system
#if defined(HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif

//#include "stdafx.h"
#include "ServerList.h"
#include "emule.h"
#include "HTTPDownloadDlg.h"
#include "SafeFile.h"

#include <wx/msgdlg.h>

#include <wx/listimpl.cpp>
//WX_DEFINE_LIST(CServerListList);

CServerList::CServerList(CPreferences* in_prefs):
  list(wxKEY_NONE)
{
	servercount = 0;
	version = 0;
	serverpos = 0;
	searchserverpos = 0;
	statserverpos = 0;
	app_prefs = in_prefs;
	//udp_timer = 0;
	udp_timer.SetOwner(theApp.emuledlg,4322);
	delservercount = 0;
	m_nLastSaved = ::GetTickCount();
}

void CServerList::AutoUpdate(){
	if (app_prefs->adresses_list.IsEmpty()){
		wxMessageBox(GetResString(IDS_ERR_EMPTYADRESSESDAT),GetResString(IDS_ERR_EMPTYADRESSESDAT_TITLE),wxICON_ERROR|wxCENTRE|wxOK);
		return;
	}
	bool bDownloaded=false;
	CString servermetdownload;
	CString servermetbackup;
	CString servermet;
	CString strURLToDownload; 
	servermetdownload.Format("%sserver_met.download",app_prefs->GetAppDir());
	servermetbackup.Format("%sserver_met.old",app_prefs->GetAppDir());
	servermet.Format("%sserver.met",app_prefs->GetAppDir());
	remove(servermetbackup.GetData());
	//printf("**removed %s\n",servermetbackup.GetData());
	remove(servermetdownload.GetData());
	//printf("**and removed %s\n",servermetdownload.GetData());
	rename(servermet.GetData(),servermetbackup.GetData());
	//printf("**renamed %s->%s\n",servermet.GetData(),servermetbackup.GetData());
	POSITION Pos = app_prefs->adresses_list.GetHeadPosition(); 
	while ((!bDownloaded) && (Pos != NULL)){
		CHTTPDownloadDlg* dlgDownload;
		strURLToDownload = app_prefs->adresses_list.GetNext(Pos); 
		//dlgDownload.m_sURLToDownload = strURLToDownload.GetBuffer();
		//dlgDownload.m_sFileToDownloadInto = servermetdownload;
		dlgDownload=new CHTTPDownloadDlg(theApp.emuledlg,wxString(strURLToDownload.GetData()),wxString(servermetdownload.GetData()));
		if (dlgDownload->ShowModal()==0) {
			bDownloaded=true;
		}
		else{
			theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_FAILEDDOWNLOADMET), strURLToDownload.GetBuffer());
		}
		delete dlgDownload;
	}
	if (bDownloaded){
		rename(servermet.GetData(), servermetdownload.GetData());
		//printf("***after renamed %s->%s\n",servermet.GetData(),servermetdownload.GetData());
		rename(servermetbackup.GetData(), servermet.GetData());
		//printf("***after renamed %s->%s\n",servermetbackup.GetData(),servermet.GetData());
	}
	else{
		remove(servermet.GetData());
		//printf("**after2: removed %s\n",servermet.GetData());
		rename(servermetbackup.GetData(),servermet.GetData());
		//printf("**after2: renamed %s\n",servermetbackup.GetData(),servermet.GetData());
	}
}

bool CServerList::Init(){
	// auto update the list by using an url
	if (app_prefs->AutoServerlist())
		AutoUpdate();
	// Load Metfile
	CString strPath;
	printf("*** reading servers\n");
	strPath.Format( "%sserver.met", app_prefs->GetAppDir());
	bool bRes = AddServermetToList(strPath, false);
	if( theApp.glob_prefs->AutoServerlist() ){
		strPath.Format( "%sserver.met", app_prefs->GetAppDir());
		bool bRes2 = AddServermetToList(strPath);
		if( !bRes && bRes2 )
			bRes = true;
	}
	// insert static servers from textfile
	strPath.Format( "%sstaticservers.dat", app_prefs->GetAppDir());
	AddServersFromTextFile(strPath);
	return bRes;
}

bool CServerList::AddServermetToList(CString strFile, bool merge){
  if (!merge)
    {
      theApp.emuledlg->serverwnd->serverlistctrl->DeleteAllItems();
      this->RemoveAllServers();
    }
  CSafeFile servermet;
  /*try*/{
    if(!wxFileExists(strFile)) {
      printf("**ei oo\n");
      theApp.emuledlg->AddLogLine(false,_("Failed to load server.met!"));
    }

    if (!servermet.Open(strFile,CFile::read)){ //CFile::modeRead|CFile::osSequentialScan)){
      theApp.emuledlg->AddLogLine(false,_("Failed to load server.met!"));
      return false;
    }
    servermet.Read(&version,1);
    if (version != 0xE0 && version != MET_HEADER){
      servermet.Close();
      theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_BADSERVERMETVERSION),version);
      return false;
    }
    uint32 fservercount;
    servermet.Read(&fservercount,4);
    
    ServerMet_Struct sbuffer;
    uint32 iAddCount = 0;

    theApp.emuledlg->serverwnd->serverlistctrl->Freeze();

    for (uint32 j = 0;j != fservercount;j++){
      // get server
      servermet.Read(&sbuffer,sizeof(ServerMet_Struct));
      CServer* newserver = new CServer(&sbuffer);
      //add tags
      for (uint32 i=0;i != sbuffer.tagcount;i++)
	newserver->AddTagFromFile(&servermet);
      // set listname for server
      if (!newserver->GetListName()){
	char* listname = new char[strlen(newserver->GetAddress())+8];
	sprintf(listname,"Server %s",newserver->GetAddress());
	newserver->SetListName(listname);
	delete listname;
      }
      if (!theApp.emuledlg->serverwnd->serverlistctrl->AddServer(newserver,true) ){
	CServer* update = theApp.serverlist->GetServerByAddress(newserver->GetAddress(), newserver->GetPort());
	if(update){
	  update->SetListName( newserver->GetListName());
	  if( newserver->GetDescription() )
	    update->SetDescription( newserver->GetDescription());
	  theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(update);
	}
	delete newserver;
      }
      else
	iAddCount++;
      // don't yield all the time
      if(j%75==0) {theApp.Yield();}
    }
    theApp.emuledlg->serverwnd->serverlistctrl->Thaw();
    
    if (!merge)
      theApp.emuledlg->AddLogLine(true,GetResString(IDS_SERVERSFOUND),fservercount);
    else
      theApp.emuledlg->AddLogLine(true,GetResString(IDS_SERVERSADDED), iAddCount, fservercount-iAddCount);
    servermet.Close();
  }
#if 0
  catch(CFileException* error){
    if (error->m_cause == CFileException::endOfFile)
      theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_BADSERVERLIST));
    else{
      char buffer[150];
      error->GetErrorMessage(buffer,150);
      theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_FILEERROR_SERVERMET),buffer);
    }
    error->Delete();	//memleak fix
  }
#endif
 return true;
}

bool CServerList::AddServer(CServer* in_server){
	if (theApp.glob_prefs->FilterBadIPs()) 
		if ( !IsGoodServerIP( in_server ))
			return false;
	CServer* test_server = GetServerByAddress(in_server->GetAddress(), in_server->GetPort());
	if (test_server){
		test_server->ResetFailedCount();
		theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer( test_server );		
		return false;
	}
	list.AddTail(in_server); //AddTail(in_server);
	return true;
}

void CServerList::ServerStats(){
	if( theApp.serverconnect->IsConnected() && list.GetCount() > 0 ) {
		CServer* ping_server = GetNextStatServer();
		CServer* test = ping_server;
		if( !ping_server )
			return;
        while(ping_server->GetLastPinged() != 0 && (::GetTickCount() - ping_server->GetLastPinged()) < UDPSERVSTATREASKTIME){ 
			ping_server = this->GetNextStatServer();
			if( ping_server == test )
				return;
		}
		if( ping_server->GetFailedCount() >= theApp.glob_prefs->GetDeadserverRetries() && theApp.glob_prefs->DeadServer() ){
			theApp.emuledlg->serverwnd->serverlistctrl->RemoveServer(ping_server);
			return;
		}
		Packet* packet = new Packet( OP_GLOBSERVSTATREQ, 4 );
		srand((unsigned)time(NULL));
		uint32 time = 0x55AA0000 + (uint16)rand();
		ping_server->SetChallenge(time);
		memcpy( packet->pBuffer, &time, 4 );
		ping_server->SetLastPinged( ::GetTickCount() );
		ping_server->AddFailedCount();
		theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer( ping_server );
		theApp.serverconnect->SendUDPPacket( packet, ping_server, true );
	}
}

/*filter Servers with invalid IP's / Port
0.*
10.*
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255
127.*
*/
bool CServerList::IsGoodServerIP(CServer* in_server){ 
	if (in_server->HasDynIP())
		return true;
	char * pch;

	char ipx[24];
	sprintf(ipx,"%s",in_server->GetFullIP());
	
	// Determine first and second number if the given IP
	pch = strtok (ipx,".");	wxString first=pch;pch=strtok(NULL,".");	wxString second=pch;

	int secondI=atoi(second);

	if (first=="172" && (secondI>=16 && secondI<=31) ) return false;

	if (first=="192" && secondI==168 ) return false;

	if (first=="0" || first=="10" || first=="127"
		|| in_server->GetPort()==0) return false;

	return true; 
}

void CServerList::RemoveServer(CServer* out_server){
	for(POSITION pos = list.GetHeadPosition(); pos != NULL; )
	{
		POSITION pos2 = pos;
		CServer* test_server = list.GetNext(pos);
		if (test_server == out_server){
			if (theApp.downloadqueue->cur_udpserver == out_server)
				theApp.downloadqueue->cur_udpserver = 0;
			list.RemoveAt(pos2);
			delservercount++;
			delete test_server;
			return;
		}
	}
}

void CServerList::RemoveAllServers(){
	for(POSITION pos = list.GetHeadPosition(); pos != NULL; pos = list.GetHeadPosition()) {
		delete list.GetAt(pos);
		list.RemoveAt(pos);
		delservercount++;
	}
}

void CServerList::GetStatus(uint32 &total, uint32 &failed, uint32 &user, uint32 &file, uint32 &tuser, uint32 &tfile,float &occ){
	total = list.GetCount();
	failed = 0;
	user = 0;
	file = 0;
	tuser=0;
	tfile = 0;
	occ=0;
	uint32 maxusers=0;
	uint32 tuserk = 0;

	CServer* curr;
	for (POSITION pos = list.GetHeadPosition(); pos !=0;list.GetNext(pos)){
		curr = (CServer*)list.GetAt(pos);
		if( curr->GetFailedCount() ){
			failed++;
		}
		else{
			user += curr->GetUsers();
			file += curr->GetFiles();
		}
		tuser += curr->GetUsers();
		tfile += curr->GetFiles();
		
		if (curr->GetMaxUsers()) {
			tuserk += curr->GetUsers(); // total users on servers with known maximum
			maxusers+=curr->GetMaxUsers();
		}
	}
	if (maxusers>0) occ=(float)(tuserk*100)/maxusers;
}

void CServerList::GetUserFileStatus(uint32 &user, uint32 &file){
	user = 0;
	file = 0;
	CServer* curr;
	for (POSITION pos = list.GetHeadPosition(); pos !=0;list.GetNext(pos)){
		curr = (CServer*)list.GetAt(pos);
		if( !curr->GetFailedCount() ){
			user += curr->GetUsers();
			file += curr->GetFiles();
		}
	}
}

CServerList::~CServerList(){
	SaveServermetToFile();
	for(POSITION pos = list.GetHeadPosition(); pos != NULL; pos = list.GetHeadPosition()) {
		delete list.GetAt(pos);
		list.RemoveAt(pos);
	}
	udp_timer.Stop();
}


#include <wx/txtstrm.h>
#include <wx/wfstream.h>

// *BSD compatibility
#if (defined(BSD) && (BSD >= 199103))
#define MAX_PATH MAXPATHLEN
#else
#define MAX_PATH 1024
#endif

void CServerList::AddServersFromTextFile(CString strFilename,bool isstaticserver) {
	wxString strLine;
	//CStdioFile f;
	//wxFFile f;
	//if (!f.Open(strFilename, CFile::modeRead | CFile::typeText))
	if(!wxFileName::FileExists(strFilename)) {
	  // no file. do nothing.
	  return;
	}
	wxFileInputStream stream(strFilename);
	if(!stream.Ok()) 
	  return;

	wxTextInputStream f(stream);

#if 0
	if(!f.Open(strFilename,"r"))
		return;
#endif

	while(strLine=f.ReadLine()) {
	  if(stream.Eof()) break; // stop iteration if end of file is met..
	  // (while won't do it for us)
		// format is host:port,Name
		if (strLine.Length() < 5)
			continue;
		if (strLine.GetChar(0) == '#' || strLine.GetChar(0) == '/')
			continue;

		// fetch host
		int pos = strLine.Find(":");
		if (pos == -1){
			pos = strLine.Find(","); 
			if (pos == -1) 
			continue;
		}
		wxString strHost = strLine.Left(pos);
		strLine = strLine.Mid(pos+1);
		// fetch  port
		pos = strLine.Find(",");
		if (pos == -1)
			continue;
		wxString strPort = strLine.Left(pos);
		strLine = strLine.Mid(pos+1);

		// Barry - fetch priority
		pos = strLine.Find(",");
		int priority = SRV_PR_HIGH;
		if (pos == 1)
		{
			wxString strPriority = strLine.Left(pos);
			try
			{
			  priority = atoi(strPriority.GetData());
				if ((priority < 0) || (priority > 2))
					priority = SRV_PR_HIGH;
			} catch (...) {}
			strLine = strLine.Mid(pos+1);
		}

		// fetch name
		wxString strName = strLine;
		strName.Replace("\r", "");
		strName.Replace("\n", "");


		// create server object and add it to the list
		CServer* nsrv = new CServer(atoi(strPort), (char*)strHost.GetData());
		nsrv->SetListName((char*)strName.GetData());
		nsrv->SetIsStaticMember(true);
		// Barry - Was always high
		nsrv->SetPreference(priority); 
		if (!theApp.emuledlg->serverwnd->serverlistctrl->AddServer(nsrv, true))
		{
			delete nsrv;
			CServer* srvexisting = GetServerByAddress((char*)strHost.GetData(), atoi(strPort));
			if (srvexisting) {
				srvexisting->SetListName((char*)strName.GetData());
				srvexisting->SetIsStaticMember(true);
				// Barry - Was always high
				srvexisting->SetPreference(priority); 
				if (theApp.emuledlg->serverwnd) theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(srvexisting);
			}
		}
	}

	//f.Close();
	//printf("todo. addserversfromtextfile needs work\n");
}




void CServerList::MoveServerDown(CServer* aServer){
   POSITION pos1, pos2;
   uint16 i = 0;
   for( pos1 = list.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
	   list.GetNext(pos1);
	   CServer* cur_server = list.GetAt(pos2);
	   if (cur_server==aServer){
		   list.AddTail(cur_server);
		   list.RemoveAt(pos2);
		   return;
	   }
	   i++;
	   if (i == list.GetCount())
		   break;
   }
}

void CServerList::Sort(){
   POSITION pos1, pos2;
   uint16 i = 0;
   for( pos1 = list.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
	   list.GetNext(pos1);
	   CServer* cur_server = list.GetAt(pos2);
	   if (cur_server->GetPreferences()== PR_HIGH){
		   list.AddHead(cur_server);
		   list.RemoveAt(pos2);
	   }
	   else if (cur_server->GetPreferences() == PR_LOW){
		   list.AddTail(cur_server);
		   list.RemoveAt(pos2);
	   }
	   i++;
	   if (i == list.GetCount())
		   break;
   }
}

CServer* CServerList::GetNextServer(){
	CServer* nextserver = 0;
	uint32 i = 0;
	if (serverpos>=((uint32)list.GetCount()) ) return 0;
	while (!nextserver && i != list.GetCount()){
		POSITION posIndex = list.FindIndex(serverpos);
		if (posIndex == NULL) {	// check if search position is still valid (could be corrupted by server delete operation)
			posIndex = list.GetHeadPosition();
			serverpos= 0;       //<<--9/27/02 zg
		}

		nextserver = list.GetAt(posIndex);
		serverpos++;
		i++;
		// TODO: Add more option to filter bad server like min ping, min users etc
		//if (nextserver->preferences = ?)
		//	nextserver = 0;
		//if (serverpos == list.GetCount()) return 0;//			serverpos = 0;
	}
	return nextserver;
}

CServer* CServerList::GetNextSearchServer(){
	CServer* nextserver = 0;
	uint32 i = 0;
	while (!nextserver && i != list.GetCount()){
		POSITION posIndex = list.FindIndex(searchserverpos);
		if (posIndex == NULL) {	// check if search position is still valid (could be corrupted by server delete operation)
			posIndex = list.GetHeadPosition();
			searchserverpos=0;
		}
		nextserver = list.GetAt(posIndex);
		searchserverpos++;
		i++;
		if (searchserverpos == list.GetCount())
			searchserverpos = 0;
	}
	return nextserver;
}

CServer* CServerList::GetNextStatServer(){
	CServer* nextserver = 0;
	uint32 i = 0;
	while (!nextserver && i != list.GetCount()){
		POSITION posIndex = list.FindIndex(statserverpos);
		if (posIndex == NULL) {	// check if search position is still valid (could be corrupted by server delete operation)
			posIndex = list.GetHeadPosition();
			statserverpos=0;
		}

		nextserver = list.GetAt(posIndex);
		statserverpos++;
		i++;
		if (statserverpos == list.GetCount())
			statserverpos = 0;
	}
	return nextserver;
}

bool CServerList::BroadCastPacket(Packet* packet){ // unused atm . but might be useful later
	if (udp_timer.IsRunning())
		return false;
	//udp_timer = SetTimer(0,4322,UDPSEARCHSPEED,CServerList::UDPTimerProc);
	udp_timer.Start(UDPSEARCHSPEED);
	broadcastpos = list.GetHeadPosition();
	broadcastpacket = packet;
	return true;
}

void CServerList::SendNextPacket(){
	if (theApp.listensocket->TooManySockets()){
	  //KillTimer(0,udp_timer);
	  udp_timer.Stop();
		delete broadcastpacket;
		return;
	}

	if (broadcastpos != 0){
		CServer* cur_server = list.GetAt(broadcastpos);
		if (cur_server != theApp.serverconnect->GetCurrentServer())
			theApp.serverconnect->SendUDPPacket(broadcastpacket,cur_server,false);
		list.GetNext(broadcastpos);
	}
	else{
	  //illTimer(0,udp_timer);
	  udp_timer.Stop();
		delete broadcastpacket;

	}
}

void CServerList::CancelUDPBroadcast(){
	if (udp_timer.IsRunning()){
	  //KillTimer(0,udp_timer);
	  //udp_timer = 0;
	  udp_timer.Stop();
		delete broadcastpacket;
	}
}

#if 0
void CALLBACK CServerList::UDPTimerProc(HWND hwnd, UINT uMsg,UINT_PTR idEvent,DWORD dwTime){
	theApp.serverlist->SendNextPacket();
}
#endif

CServer* CServerList::GetNextServer(CServer* lastserver){
	if (list.IsEmpty())
		return 0;
	if (!lastserver) return list.GetHead();

	POSITION pos = list.Find(lastserver);
	if (!pos){
		return list.GetHead();
	}
	list.GetNext(pos);
	if (!pos)
		return NULL;
	else
		return list.GetAt(pos);
}

CServer* CServerList::GetServerByAddress(char* address, uint16 port){
	for (POSITION pos = list.GetHeadPosition();pos != 0;list.GetNext(pos)){
        CServer *s = list.GetAt(pos);   // i_a: small speed optimization 
        if (port == s->GetPort() && !strcmp(s->GetAddress(),address)) 
          return s; 
	}
	return NULL;
}

bool CServerList::SaveServermetToFile(){
  m_nLastSaved=::GetTickCount(); // oops.. don't save ALL the time :)

	char* newservermet = new char[strlen(app_prefs->GetAppDir())+MAX_PATH];
	sprintf(newservermet,"%sserver.met.new",app_prefs->GetAppDir());
//	theApp.emuledlg->AddLogLine( false, "%s", newservermet );
	{
	FILE* servermet = fopen(newservermet, "wb");
	if (!servermet){
		theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_SAVESERVERMET));
		delete[] newservermet;	//mf
		return false;
	}
	version = 0xE0;

	fwrite( &version, 1, 1, servermet);
	uint32 fservercount = list.GetCount();
	fwrite(&fservercount,4,1,servermet);
	ServerMet_Struct sbuffer;
	CServer* nextserver;

	for (uint32 j = 0;j != fservercount;j++){
		nextserver = this->GetServerAt(j);
		sbuffer.ip = nextserver->GetIP();
		sbuffer.port = nextserver->GetPort();
		uint16 tagcount = 7;
		if (nextserver->GetListName())
			tagcount++;
		if (nextserver->GetDynIP())
			tagcount++;
		if (nextserver->GetDescription())
			tagcount++;
		sbuffer.tagcount = tagcount;
		fwrite( &sbuffer, 1, sizeof(ServerMet_Struct),servermet);
		
		if( nextserver->GetListName() ){
			CTag servername( ST_SERVERNAME, nextserver->GetListName() );
			servername.WriteTagToFile(servermet);
		}
		if( nextserver->GetDynIP() ){
			CTag serverdynip( ST_DYNIP, nextserver->GetDynIP() );
			serverdynip.WriteTagToFile(servermet);
		}
		if( nextserver->GetDescription() ){
			CTag serverdesc( ST_DESCRIPTION, nextserver->GetDescription() );
			serverdesc.WriteTagToFile(servermet);
		}
		CTag serverfail(ST_FAIL, nextserver->GetFailedCount() );
		serverfail.WriteTagToFile(servermet);
		CTag serverpref( ST_PREFERENCE, nextserver->GetPreferences() );
		serverpref.WriteTagToFile(servermet);
		CTag serveruser("users", nextserver->GetUsers() );
		serveruser.WriteTagToFile(servermet);
		CTag serverfiles("files", nextserver->GetFiles() );
		serverfiles.WriteTagToFile(servermet);
		CTag serverping(ST_PING, nextserver->GetPing() );
		serverping.WriteTagToFile(servermet);
		CTag serverlastp(ST_LASTPING, nextserver->GetLastPinged() );
		serverlastp.WriteTagToFile(servermet);
		CTag servermaxusers(ST_MAXUSERS, nextserver->GetMaxUsers() );
		servermaxusers.WriteTagToFile(servermet);
	}
	fclose(servermet);
	char* curservermet = new char[strlen(app_prefs->GetAppDir())+20];
	char* oldservermet = new char[strlen(app_prefs->GetAppDir())+20];
	sprintf(curservermet,"%sserver.met",app_prefs->GetAppDir());
	sprintf(oldservermet,"%sserver_met.old",app_prefs->GetAppDir());
	remove(oldservermet);
	rename(curservermet,oldservermet);
	rename(newservermet,curservermet);
	delete[] oldservermet;
	delete[] curservermet;
	}
#if 0
	catch(CFileException* error) {
		OUTPUT_DEBUG_TRACE();
		theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_SAVESERVERMET2));
		delete[] newservermet;	//mf
		error->Delete();
		return false;
	}
#endif
	delete[] newservermet;
	return true;
}

void CServerList::Process()
{
	if (::GetTickCount() - m_nLastSaved > 180000)
		this->SaveServermetToFile();
}
